package part3

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
)

const dbFile = "blockchain_db.json"

//区块链
type Blockchain struct {
	//map[区块的hash] = 区块
	DB map[string]Block `json:"DB"`
	// l 存最新的区块hash值
	L string `json:"L"`
}

func CreateBlockchain() *Blockchain {
	if !PathExists(dbFile) {
		//如果文件不存在，则创建一个blockchain的json文件
		f, err := os.Create(dbFile)
		if err != nil {
			fmt.Println(err.Error())
		}
		defer f.Close()
	}

	//创世区块
	block := NewGenesisBlock()
	var db map[string]Block = map[string]Block{}
	hash := hex.EncodeToString(block.Hash)
	db[hash] = *block
	bc := &Blockchain{
		DB: db,
		L:  hash,
	}
	//写入文件
	data, _ := json.Marshal(bc)
	err := ioutil.WriteFile(dbFile, data, 0666)
	if err != nil {
		fmt.Println("write fail")
	}
	return bc
}

//获得区块链
func GetBlockchain() *Blockchain {
	if !PathExists(dbFile) {
		log.Fatal("请先创建区块链")
		return nil
	}

	content, err := ioutil.ReadFile(dbFile)
	if err != nil {
		panic(err)
	}
	var bc Blockchain
	err = json.Unmarshal(content, &bc)
	if err != nil {
		panic(err)
	}
	return &bc
}

//save区块链
func (bc *Blockchain) SaveBlockchain() *Blockchain {
	if !PathExists(dbFile) {
		log.Fatal("请先创建区块链")
		return nil
	}

	//写入文件
	data, _ := json.Marshal(bc)
	err := ioutil.WriteFile(dbFile, data, 0666)
	if err != nil {
		fmt.Println("write fail")
	}
	return bc
}

//添加区块
func (bc *Blockchain) AddBlock(data string) {
	//最新的区块
	prevBlock := bc.DB[bc.L]
	//新建区块
	newBlock := NewBlock(data, prevBlock.Hash, prevBlock.Height+1)
	hash := newBlock.GetHashString()
	bc.DB[hash] = *newBlock
	bc.L = hash
	//保存
	bc.SaveBlockchain()
}

//创世区块
func NewGenesisBlock() *Block {
	return NewBlock("Genesis Block", []byte{}, 0)
}

//打印区块链
func (bc *Blockchain) Print() {
	bci := bc.Iterator()
	for {
		//循环所有的区块
		block := bci.Next()
		fmt.Printf(" %v\n", block)
		if len(block.PrevBlockHash) == 0 {
			break
		}
	}
}
